#include "Model.h"

#ifndef TINYOBJLOADER_IMPLEMENTATION
#define TINYOBJLOADER_IMPLEMENTATION
#endif

#include "utils/tiny_obj_loader.h"
#include "../../Utils/FileUtil.h"
#include <unordered_map>

Model::Model(const std::string path)
{
	tinyobj::attrib_t attrib;
	std::vector<tinyobj::shape_t> shapes;
	std::vector<tinyobj::material_t> materials;
	std::string warn, err;
	std::string filePath = FileUtil::GetAssetPath() + std::string("\\Models\\") + path;
	assert(tinyobj::LoadObj(&attrib, &shapes, &materials, &warn, &err, filePath.c_str()));


	std::unordered_map<Vertex, uint32> uniqueVertices;

	for (const auto& shape : shapes) {
		for (const auto& index : shape.mesh.indices) {
			Vertex vertex{};

			vertex.Position = {
					attrib.vertices[3 * index.vertex_index + 0],
					attrib.vertices[3 * index.vertex_index + 1],
					attrib.vertices[3 * index.vertex_index + 2]
			};

			if (attrib.normals.size() > 0)
			{
				vertex.Normal = {
						attrib.normals[3 * index.normal_index + 0],
						attrib.normals[3 * index.normal_index + 1],
						attrib.normals[3 * index.normal_index + 2]
				};
				// vertex.Normal = glm::normalize(vertex.Normal);
			}

			if (attrib.texcoords.size() > 0)
			{
				vertex.TexC = {
						attrib.texcoords[2 * index.texcoord_index + 0],
						1.0f - attrib.texcoords[2 * index.texcoord_index + 1]
				};
			}

			if (uniqueVertices.count(vertex) == 0) {
				uniqueVertices[vertex] = static_cast<uint32>(mVertexs.size());
				mVertexs.push_back(vertex);
			}

			mIndices.push_back(uniqueVertices[vertex]);
		}
	}

	GeometryGenerator geometryGenerator;
	// geometryGenerator.GenerateNormals(mVertexs.data(), mVertexs.size(), mIndices.data(), mIndices.size());
	geometryGenerator.GenerateTangents(mVertexs.data(), mVertexs.size(), mIndices.data(), mIndices.size());
}

Model::Model(GeometryGenerator::MeshData& meshData, bool generateTangent)
{
	mVertexs.assign(meshData.Vertices.begin(), meshData.Vertices.end());
	mIndices.assign(meshData.Indices32.begin(), meshData.Indices32.end());

	if (generateTangent)
	{
		GeometryGenerator geometryGenerator;
		// geometryGenerator.GenerateNormals(mVertexs.data(), mVertexs.size(), mIndices.data(), mIndices.size());
		geometryGenerator.GenerateTangents(mVertexs.data(), mVertexs.size(), mIndices.data(), mIndices.size());
	}
}

